package tool

import cats.data.Validated
import shared.pojo.Predict.PredictData
import implicits.Implicits._

/**
 * Created by yz on 23/6/2021
 */
class PredictDataValidTool(data: PredictData) {

  def validAst = {
    val v = data.ast
    val info = "天门冬氨酸氨基转移酶"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      val min = 0
      val max = 1000
      Validated.cond(v.toDouble >= min && v.toDouble <= max, true, s"${info}必须处于${min}到${max}之间！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validAlt = {
    val v = data.alt
    val info = "丙氨酸氨基转移酶"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      val min = 0
      val max = 2000
      Validated.cond(v.toDouble >= min && v.toDouble <= max, true, s"${info}必须处于${min}到${max}之间！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validPlt = {
    val v = data.plt
    val info = "血小板计数"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      val min = 0
      val max = 1000
      Validated.cond(v.toDouble >= min && v.toDouble <= max, true, s"${info}必须处于${min}到${max}之间！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validTyr = {
    val v = data.tyr
    val info = "L-酪氨酸"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validTca = {
    val v = data.tca
    val info = "牛磺胆酸"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validAge = {
    val age = data.age
    Validated.cond(age.nonBlank, true, s"年龄不能为空！").andThen { b =>
      Validated.cond(age.isInt, true, s"年龄必须为整数！")
    }.andThen { b =>
      Validated.cond(age.toInt >= 18 && age.toInt <= 100, true, s"年龄必须处于18到100之间！")
    }
  }

  def validSampleId = {
    val v = data.sampleId
    val info = "样本号"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！")
  }

  def validPhe = {
    val v = data.phe
    val (info, min, max) = ("苯丙氨酸", 5, 1000)
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.toDouble >= min && v.toDouble <= max, true, s"${info}必须处于${min}到${max}之间！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validTrp = {
    val v = data.trp
    val (info, min, max) = ("色氨酸", 5, 1000)
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.toDouble >= min && v.toDouble <= max, true, s"${info}必须处于${min}到${max}之间！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validValine = {
    val v = data.valine
    val (info, min, max) = ("缬氨酸", 5, 1000)
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.toDouble >= min && v.toDouble <= max, true, s"${info}必须处于${min}到${max}之间！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validCa = {
    val v = data.ca
    val info = "胆酸"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validMet = {
    val v = data.met
    val (info, min, max) = ("甲硫氨酸", 5, 1000)
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.toDouble >= min && v.toDouble <= max, true, s"${info}必须处于${min}到${max}之间！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validGca = {
    val v = data.gca
    val info = "甘氨氧胆酸"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validGcdca = {
    val v = data.gcdca
    val info = "甘氨鹅脱氧胆酸"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

  def validTcdca = {
    val v = data.tcdca
    val info = "牛磺鹅脱氧胆酸"
    Validated.cond(v.nonBlank, true, s"${info}不能为空！").andThen { b =>
      Validated.cond(v.isDouble, true, s"${info}必须为实数！")
    }.andThen { b =>
      Validated.cond(v.matches("^\\d*(\\.\\d{1,3})?$"), true, s"${info}最多包含三位小数！")
    }
  }

}

object PredictDataValidTool {

  def valid(data: PredictData) = {
    val fileValidTool = new PredictDataValidTool(data)
    import fileValidTool._
    validAge.andThen { b =>
      validSampleId
    }.andThen { b =>
      validAst
    }.andThen { b =>
      validAlt
    }.andThen { b =>
      validPlt
    }.andThen { b =>
      validTyr
    }.andThen { b =>
      validTca
    }.andThen { b =>
      validPhe
    }.andThen { b =>
      validTrp
    }.andThen { b =>
      validValine
    }.andThen { b =>
      validCa
    }.andThen { b =>
      validMet
    }.andThen { b =>
      validGca
    }.andThen { b =>
      validGcdca
    }.andThen { b =>
      validTcdca
    }
  }

}
